//@author A0084731E

import java.io.*;
import java.util.*;

public class Transactions {

	// ATTRIBUTES
	protected int _currID;
	protected List<Transaction> _transactions;
	protected String _currency;
	protected HashMap<String, Double> _exRate;

	// CONSTANTS
	protected static final String ASSETS_FOLDER = "assets";
	protected static final String ASSETS_PATH = System.getProperty("user.dir") + "/" + ASSETS_FOLDER + "/";
	protected static final String EXCHANGE_RATE_FILENAME = "exchange_rate.txt";
	protected static final String EXCHANGE_RATE_PATH = ASSETS_PATH + EXCHANGE_RATE_FILENAME;
	
	// CONSTRUCTOR
	public Transactions() {
		this._currID = 0;
		this._transactions = new ArrayList<Transaction>();
		this._currency = Account.DEFAULT_CURRENCY;
		this._exRate = new HashMap<String, Double>();
		this.initExRate();
	}

	// METHODS
	// Getters
	public String getCurrency() {
		return this._currency;
	}
	public int getCurrID() {
		return this._currID;
	}
	public HashMap<String, Double> getExRate() {
		return this._exRate;
	}
	public List<Transaction> getTransactions() {
		return this._transactions;
	}
	public Transaction getTransaction(int id) {
		for (int i=0; i<this.getTransactions().size(); i++) {
			if (this.getTransactions().get(i).getID() == id) {
				return this.getTransactions().get(i);
			}
		}
		return null;
	}
	public int size() {
		return this.getTransactions().size();
	}
	
	// Setters
	public void setCurrency(String currency) {
		this._currency = currency;
	}
	
	// Generate new ID
	public int newID() {
		return this._currID++;
	}
	
	// Initialise the _exRate	
	public void initExRate(){
		File file = new File(EXCHANGE_RATE_PATH);
		try {
			Scanner sc = new Scanner(file);
			while(sc.hasNext()) {
				this._exRate.put(sc.next(), sc.nextDouble());
			}
			sc.close();
		} catch (FileNotFoundException e) {
			System.out.println("Please place " + EXCHANGE_RATE_FILENAME + " file in the Simplex asset folder");
		}
		
	}

	// Add transaction
	public boolean addTransaction(Transaction transaction) {
		transaction.setID(this.newID());
		this.getTransactions().add(transaction);
		return true;
	}
	public boolean addTransaction(int id,Transaction transaction) {
		transaction.setID(id);
		this.getTransactions().add(transaction);
		return true;
	}
	// Delete transaction
	public Transaction deleteTransaction(int id) {
		Transaction transaction = null;
		for (int i=0; i<this.size(); i++) {
			if (this.getTransactions().get(i).getID() == id) {
				transaction = this.getTransactions().remove(i);
			}
		}
		return transaction;
	}

	public boolean deleteTransaction(Transaction transaction){
		this.getTransactions().remove(transaction);
		return true;
	}
	// Update transaction
	public Transaction updateTransaction(int id, Transaction transaction) {
		transaction.setID(id);
		Transaction temp = this.getTransaction(id);
		int i = this.getTransactions().indexOf(temp);
		return this.getTransactions().set(i, transaction);
	}

	// FILTERS
	// Filter transactions by date	
	public List<Transaction> filterByDate(String str) {
		String[] transaction = str.split("\\.");
		int[] date = new int[transaction.length];
		for (int i=0; i<transaction.length; i++) {
			date[i] = Integer.parseInt(transaction[i]);
		}
		if (date.length == 1) {
			return filterByDate(date[0]);
		} else if(date.length == 2) {
			return filterByDate(date[1], date[0]);
		} else {
			return filterByDate(date[2], date[1], date[0]);
		}
	}

	public List<Transaction> filterByDate(int year) {
		List<Transaction> result = new ArrayList<Transaction>();
		for (int i=0; i<this.size(); i++) {
			Transaction transaction = this.getTransactions().get(i);
			if (transaction.getDate().get(Calendar.YEAR)==year) {
				result.add(transaction);
			}
		}
		return result;
	}

	public List<Transaction> filterByDate(int year, int month) {
		List<Transaction> result = new ArrayList<Transaction>();
		for (int i=0; i<this.size(); i++) {
			Transaction transaction = this.getTransactions().get(i);
			if ((transaction.getDate().get(Calendar.YEAR)==year)&&(transaction.getDate().get(Calendar.MONTH)==(month-1))) {
				result.add(transaction);
			}
		}
		return result;	
	}

	public List<Transaction> filterByDate(int year, int month, int day){
		List<Transaction> result = new ArrayList<Transaction>();
		for (int i=0; i<this.size(); i++) {
			Transaction transaction = this.getTransactions().get(i);
			if ((transaction.getDate().get(Calendar.YEAR)==year)&&(transaction.getDate().get(Calendar.MONTH)==(month-1))
					&&(transaction.getDate().get(Calendar.DAY_OF_MONTH)==day)) {
				result.add(transaction);
			}
		}
		return result;	
	}

	// Filter transactions by category
	public List<Transaction> filterByCategory(String category){
		List<Transaction> result = new ArrayList<Transaction>();
		for (int i=0; i<this.size(); i++) {
			Transaction transaction = this.getTransactions().get(i);
			if (transaction.getCategory().equals(category)) {
				result.add(transaction);
			}
		}
		return result;
	}

	//Filter transactions by payment methods
	public List<Transaction> filterByPaymentMethod(String method){
		List<Transaction> result = new ArrayList<Transaction>();
		for (int i=0; i<this.size(); i++) {
			Transaction transaction = this.getTransactions().get(i);
			if (transaction.getPaymentMethod().equals(method)) {
				result.add(transaction);
			}
		}
		return result;
	}

	// Filter transactions by type(EXPENSE/DEPOSIT)
	public List<Transaction> filterByType(String type){
		List<Transaction> result = new ArrayList<Transaction>();
		for (int i=0; i<this.size(); i++) {
			Transaction transaction = this.getTransactions().get(i);
			if (transaction.getType().toString().equals(type)) {
				result.add(transaction);
			}
		}
		return result;
	}
	//Filter transactions by status(PAID/OUTSTANDING)
	public List<Transaction> filterByStatus(String status){
		List<Transaction> result = new ArrayList<Transaction>();
		for (int i=0; i<this.size(); i++) {
			Transaction transaction = this.getTransactions().get(i);
			if (transaction.getStatus().toString().equals(status)) {
				result.add(transaction);
			}
		}
		return result;
	}

	//check whether the ArrayList is empty
	public boolean isEmpty(){
		return this.getTransactions().isEmpty();
	}

	// Currency Conversion
	public void convertCurrency(String newCurrency){		 
		double oldExRate = this.getExRate().get(this.getCurrency());
		double newExRate = this.getExRate().get(newCurrency);
		
		for (int i=0;i<this.size();i++) {
			Transaction transaction = this.getTransactions().get(i);
			transaction.setValue(transaction.getValue()/oldExRate*newExRate);			
		}
		
		this.setCurrency(newCurrency);
		
	}

	// String representation
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		for (int i=0; i<this.size(); i++) {
			sb.append(this.getTransactions().get(i).toString() + "\n");
		}
		return sb.toString();
	}
	
}
